home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / term43-source.lha / Extras / Source / term-Source.lha / termConsole.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-15  |  55.1 KB  |  3,398 lines

  1. /*
  2. **    termConsole.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Character set modes. */
  13.  
  14. enum    {    MODE_STANDARD,MODE_GFX };
  15.  
  16.     /* Hints for the data flow scanner. */
  17.  
  18. STATIC WORD        ScanStart,
  19.             ScanEnd;
  20.  
  21. STATIC WORD __far    AttentionCount[SCAN_COUNT],
  22.             AttentionLength[SCAN_COUNT],
  23.             FlowCount;
  24.  
  25.     /* Temporary console working buffer. */
  26.  
  27. STATIC UBYTE __far    ConTempBuffer[512];
  28.  
  29.     /* Text output data. */
  30.  
  31. STATIC UBYTE        CurrentFontScale,FontScalingRequired;
  32. STATIC WORD        LastPrintableColumn;
  33.  
  34.     /* ConTranslateSetup():
  35.      *
  36.      *    Set up for buffer translation.
  37.      */
  38.  
  39. STATIC VOID __inline
  40. ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  41. {
  42.     Handle -> LocalBuffer        = NULL;
  43.     Handle -> LocalLen        = 0;
  44.  
  45.     Handle -> SourceBuffer        = SourceBuffer;
  46.     Handle -> SourceLen        = SourceLen;
  47.  
  48.     Handle -> DestinationBuffer    = DestinationBuffer;
  49.     Handle -> DestinationLen    = DestinationLen;
  50.  
  51.     Handle -> Table            = Table;
  52. }
  53.  
  54.     /* ConTranslateBuffer(struct TranslationHandle *Handle):
  55.      *
  56.      *    Translate buffer contents according to
  57.      *    translation table contents.
  58.      */
  59.  
  60. STATIC LONG __inline
  61. ConTranslateBuffer(struct TranslationHandle *Handle)
  62. {
  63.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  64.     register LONG                 BytesWritten    = 0;
  65.     register struct TranslationEntry    *Entry;
  66.  
  67.         /* Are we to return any translated data? */
  68.  
  69.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  70.     {
  71.             /* Decrement number of bytes in buffer. */
  72.  
  73.         Handle -> LocalLen--;
  74.  
  75.             /* Return next character. */
  76.  
  77.         *Data++ = *Handle -> LocalBuffer++;
  78.  
  79.             /* Add another byte. */
  80.  
  81.         BytesWritten++;
  82.     }
  83.  
  84.         /* Loop until done. */
  85.  
  86.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  87.     {
  88.             /* Another byte eaten. */
  89.  
  90.         Handle -> SourceLen--;
  91.  
  92.             /* Get table entry. */
  93.  
  94.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  95.         {
  96.                 /* Copy to local data area. */
  97.  
  98.             Handle -> LocalBuffer    = Entry -> String;
  99.             Handle -> LocalLen    = Entry -> Len;
  100.  
  101.                 /* Translate the data. */
  102.  
  103.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  104.             {
  105.                     /* Decrement number of bytes in buffer. */
  106.  
  107.                 Handle -> LocalLen--;
  108.  
  109.                     /* Return next character. */
  110.  
  111.                 *Data++ = *Handle -> LocalBuffer++;
  112.  
  113.                     /* Add another byte. */
  114.  
  115.                 BytesWritten++;
  116.             }
  117.         }
  118.     }
  119.  
  120.     return(BytesWritten);
  121. }
  122.  
  123.     /* TrapFilter(register STRPTR Data,register LONG Size):
  124.      *
  125.      *    Handle the trap list, similar to FlowFilter().
  126.      */
  127.  
  128. STATIC VOID __regargs
  129. TrapFilter(register STRPTR Data,register LONG Size)
  130. {
  131.     STATIC LONG WaitCount = 0;
  132.  
  133.     struct List    *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
  134.     struct TrapNode    *Node;
  135.  
  136.     register UBYTE c,Mask;
  137.  
  138.     ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  139.  
  140.     if(Config -> SerialConfig -> StripBit8)
  141.         Mask = 0x7F;
  142.     else
  143.         Mask = 0xFF;
  144.  
  145.     do
  146.     {
  147.         register BOOLEAN MatchMade;
  148.  
  149.         c = (*Data++) & Mask;
  150.  
  151.         do
  152.         {
  153.             MatchMade = FALSE;
  154.  
  155.             for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  156.             {
  157.                 if(Node -> Count == WaitCount)
  158.                 {
  159.                     if(c == (Node -> Sequence[WaitCount] & Mask))
  160.                     {
  161.                         MatchMade = TRUE;
  162.  
  163.                         if(++Node -> Count == Node -> SequenceLen)
  164.                         {
  165.                             struct DataMsg *Msg;
  166.  
  167.                             Node -> Count = 0;
  168.  
  169.                             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
  170.                             {
  171.                                 Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
  172.                                 Msg -> Data = (STRPTR)(Msg + 1);
  173.  
  174.                                 strcpy(Msg -> Data,Node -> Command);
  175.  
  176.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  177.                             }
  178.                         }
  179.                     }
  180.                 }
  181.             }
  182.  
  183.             if(MatchMade)
  184.                 WaitCount++;
  185.             else
  186.             {
  187.                 if(WaitCount)
  188.                 {
  189.                     WaitCount = 0;
  190.  
  191.                     for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  192.                         Node -> Count = 0;
  193.                 }
  194.                 else
  195.                     break;
  196.             }
  197.         }
  198.         while(!WaitCount);
  199.     }
  200.     while(--Size);
  201.  
  202.     ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  203. }
  204.  
  205.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  206.      *
  207.      *    Data flow filter.
  208.      */
  209.  
  210. STATIC VOID __regargs
  211. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  212. {
  213.     register UBYTE c;
  214.  
  215.         /* Run until done. */
  216.  
  217.     do
  218.     {
  219.         if(c = (*Data++ & Mask))
  220.         {
  221.  
  222.                 /* We already got a `CONNECT',
  223.                  * Continue scanning the serial output
  224.                  * data for the actual baud rate.
  225.                  */
  226.  
  227.             if(BaudPending)
  228.             {
  229.                 if(c < ' ')
  230.                 {
  231.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  232.                         BaudCount--;
  233.  
  234.                     BaudBuffer[BaudCount] = 0;
  235.  
  236.                     FlowInfo . Connect = TRUE;
  237.                     FlowInfo . Changed = TRUE;
  238.  
  239.                     BaudPending = FALSE;
  240.  
  241.                     DTERate = GetBaudRate(BaudBuffer);
  242.  
  243.                     if(Quiet && Size > 1)
  244.                     {
  245.                         DataHold = Data;
  246.                         DataSize = Size - 1;
  247.                     }
  248.                 }
  249.                 else
  250.                 {
  251.                     if(BaudCount || c != ' ')
  252.                     {
  253.                         BaudBuffer[BaudCount++] = c;
  254.  
  255.                         if(BaudCount == 79)
  256.                         {
  257.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  258.                                 BaudCount--;
  259.  
  260.                             BaudBuffer[BaudCount] = 0;
  261.  
  262.                             FlowInfo . Connect = TRUE;
  263.                             FlowInfo . Changed = TRUE;
  264.  
  265.                             BaudPending = FALSE;
  266.  
  267.                             DTERate = GetBaudRate(BaudBuffer);
  268.  
  269.                             if(Quiet && Size > 1)
  270.                             {
  271.                                 DataHold = Data;
  272.                                 DataSize = Size - 1;
  273.                             }
  274.                         }
  275.                     }
  276.                 }
  277.             }
  278.             else
  279.             {
  280.                 register BYTE MatchMade;
  281.                 register WORD i;
  282.  
  283.                 do
  284.                 {
  285.                     MatchMade = FALSE;
  286.  
  287.                         /* Scan all ID strings for matches. */
  288.  
  289.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  290.                     {
  291.                             /* This sequence is a likely
  292.                              * match.
  293.                              */
  294.  
  295.                         if(AttentionCount[i] == FlowCount)
  296.                         {
  297.                                 /* Does the character
  298.                                  * fit into the sequence?
  299.                                  */
  300.  
  301.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  302.                             {
  303.                                 MatchMade = TRUE;
  304.  
  305.                                     /* Did we hit the
  306.                                      * last character
  307.                                      * in the sequence?
  308.                                      */
  309.  
  310.                                 if(++AttentionCount[i] == AttentionLength[i])
  311.                                 {
  312.                                         /* We've got a valid
  313.                                          * sequence, now look
  314.                                          * which flags to change.
  315.                                          */
  316.  
  317.                                     switch(i)
  318.                                     {
  319.                                             /* We got a `no carrier' message. */
  320.  
  321.                                         case SCAN_NOCARRIER:
  322.  
  323.                                             if(!FlowInfo . NoCarrier)
  324.                                             {
  325.                                                 FlowInfo . NoCarrier    = TRUE;
  326.                                                 FlowInfo . Changed    = TRUE;
  327.                                             }
  328.  
  329.                                             break;
  330.  
  331.                                             /* Got another call. */
  332.  
  333.                                         case SCAN_RING:
  334.  
  335.                                             if(!FlowInfo . Ring)
  336.                                             {
  337.                                                 FlowInfo . Ring        = TRUE;
  338.                                                 FlowInfo . Changed    = TRUE;
  339.                                             }
  340.  
  341.                                             break;
  342.  
  343.                                             /* Got a voice call. */
  344.  
  345.                                         case SCAN_VOICE:
  346.  
  347.                                             if(!FlowInfo . Voice)
  348.                                             {
  349.                                                 FlowInfo . Voice    = TRUE;
  350.                                                 FlowInfo . Changed    = TRUE;
  351.                                             }
  352.  
  353.                                             break;
  354.  
  355.                                             /* Got a connect message. */
  356.  
  357.                                         case SCAN_CONNECT:
  358.  
  359.                                             ObtainSemaphore(&OnlineSemaphore);
  360.  
  361.                                             if(!Online)
  362.                                             {
  363.                                                 BaudBuffer[0]    = 0;
  364.  
  365.                                                 BaudPending    = TRUE;
  366.                                                 BaudCount    = 0;
  367.                                             }
  368.  
  369.                                             ReleaseSemaphore(&OnlineSemaphore);
  370.  
  371.                                             break;
  372.  
  373.                                             /* Line is busy. */
  374.  
  375.                                         case SCAN_BUSY:
  376.  
  377.                                             if(!FlowInfo . Busy)
  378.                                             {
  379.                                                 FlowInfo . Busy        = TRUE;
  380.                                                 FlowInfo . Changed    = TRUE;
  381.                                             }
  382.  
  383.                                             break;
  384.  
  385.                                         case SCAN_NODIALTONE:
  386.  
  387.                                             if(!FlowInfo . NoDialTone)
  388.                                             {
  389.                                                 FlowInfo . NoDialTone    = TRUE;
  390.                                                 FlowInfo . Changed    = TRUE;
  391.                                             }
  392.  
  393.                                             break;
  394.  
  395.                                         default:
  396.  
  397.                                             if(!FlowInfo . Signature)
  398.                                             {
  399.                                                 FlowInfo . Signature    = i;
  400.                                                 FlowInfo . Changed    = TRUE;
  401.                                             }
  402.  
  403.                                             break;
  404.                                     }
  405.                                 }
  406.                             }
  407.                         }
  408.                     }
  409.  
  410.                     if(MatchMade)
  411.                         FlowCount++;
  412.                     else
  413.                     {
  414.                         if(FlowCount)
  415.                         {
  416.                             FlowCount = 0;
  417.  
  418.                             memset(AttentionCount,0,sizeof(AttentionCount));
  419.                         }
  420.                         else
  421.                             break;
  422.                     }
  423.                 }
  424.                 while(!FlowCount);
  425.             }
  426.         }
  427.     }
  428.     while(--Size);
  429. }
  430.  
  431.     /* StripSequence():
  432.      *
  433.      *    Strips a string from ESC and CSI introduced control
  434.      *    sequences.
  435.      */
  436.  
  437. STATIC LONG __regargs
  438. StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
  439. {
  440.     STATIC BYTE    HasESC    = FALSE,
  441.             HasCSI    = FALSE;
  442.     LONG        Size    = 0;
  443.  
  444.     while(Length--)
  445.     {
  446.         if(HasESC)
  447.         {
  448.             if(*Src == '[')
  449.             {
  450.                 HasESC = FALSE;
  451.                 HasCSI = TRUE;
  452.             }
  453.             else
  454.             {
  455.                 if(*Src >= '0')
  456.                     HasESC = FALSE;
  457.             }
  458.  
  459.             Src++;
  460.  
  461.             continue;
  462.         }
  463.  
  464.         if(HasCSI)
  465.         {
  466.             if(*Src >= '@')
  467.                 HasCSI = FALSE;
  468.  
  469.             Src++;
  470.  
  471.             continue;
  472.         }
  473.  
  474.         switch(*Src)
  475.         {
  476.             case CAN:
  477.             case SUB:
  478.  
  479.                 HasESC = HasCSI = FALSE;
  480.                 break;
  481.  
  482.             case '\r':
  483.  
  484.                 break;
  485.  
  486.             case ESC:
  487.  
  488.                 HasESC = TRUE;
  489.                 break;
  490.  
  491.             case CSI:
  492.  
  493.                 HasCSI = TRUE;
  494.                 break;
  495.  
  496.             default:
  497.  
  498.                 if(IsPrintable[*Src])
  499.                 {
  500.                     *Dst++ = *Src;
  501.  
  502.                     Size++;
  503.                 }
  504.  
  505.                 break;
  506.         }
  507.  
  508.         Src++;
  509.     }
  510.  
  511.     return(Size);
  512. }
  513.  
  514.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  515.      *
  516.      *    Raw text output routine, printer capture flavour.
  517.      */
  518.  
  519. STATIC VOID
  520. ConOutputPrinter(STRPTR Buffer,LONG Size)
  521. {
  522.     if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
  523.     {
  524.         BlockWindows();
  525.  
  526.         if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  527.             ClosePrinterCapture(TRUE);
  528.  
  529.         ReleaseWindows();
  530.     }
  531. }
  532.  
  533.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  534.      *
  535.      *    Raw text output routine, GFX text flavour.
  536.      */
  537.  
  538. STATIC VOID
  539. ConOutputGFX(STRPTR Buffer,LONG Size)
  540. {
  541.     register WORD Offset;
  542.  
  543.         /* Do we still have a character in the
  544.          * magnificient buffer?
  545.          */
  546.  
  547.     while(Size)
  548.     {
  549.             /* Cursor is positioned at
  550.              * the right hand side of the
  551.              * display. If auto-wrap is
  552.              * enabled, perform some
  553.              * kind of CR/LF, else leave
  554.              * the cursor where it is and
  555.              * quit the show.
  556.              */
  557.  
  558.         if(CursorX > LastPrintableColumn)
  559.         {
  560.                 /* Wrap cursor. */
  561.  
  562.             if(Config -> EmulationConfig -> LineWrap)
  563.             {
  564.                     /* Move to beginning of next line. */
  565.  
  566.                 CursorX = 0;
  567.  
  568.                 DownLine();
  569.  
  570.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  571.  
  572.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  573.  
  574.                 LastPrintableColumn = LastColumn;
  575.  
  576.                     /* Reposition cursor, don't redraw it. */
  577.  
  578.                 RepositionCursor();
  579.             }
  580.             else
  581.             {
  582.                     /* Stop the cursor. */
  583.  
  584.                 CursorX = LastPrintableColumn;
  585.  
  586.                     /* Make it reappear. */
  587.  
  588.                 RepositionCursor();
  589.  
  590.                 return;
  591.             }
  592.         }
  593.  
  594.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  595.             Offset = Size;
  596.  
  597.         if(Config -> EmulationConfig -> InsertMode)
  598.         {
  599.             RasterShiftChar(Offset);
  600.  
  601.             ScrollLineShiftChar(Offset);
  602.  
  603.             ShiftChar(Offset);
  604.         }
  605.  
  606.         RasterPutString(Buffer,Offset);
  607.  
  608.         ScrollLinePutString(Offset);
  609.  
  610.         if(FontScalingRequired)
  611.             PrintScaled(Buffer,Offset,CurrentFontScale);
  612.         else
  613.             GfxText(RPort,Buffer,Offset);
  614.  
  615.         Buffer    += Offset;
  616.  
  617.         Size    -= Offset;
  618.  
  619.         CursorX    += Offset;
  620.     }
  621.  
  622.     RepositionCursor();
  623. }
  624.  
  625.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  626.      *
  627.      *    Raw text output routine, normal text flavour.
  628.      */
  629.  
  630. STATIC VOID
  631. ConOutputNormal(STRPTR Buffer,LONG Size)
  632. {
  633.     register WORD Offset;
  634.  
  635.     while(Size)
  636.     {
  637.         if(CursorX > LastPrintableColumn)
  638.         {
  639.             if(Config -> EmulationConfig -> LineWrap)
  640.             {
  641.                 CursorX = 0;
  642.  
  643.                 DownLine();
  644.  
  645.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  646.  
  647.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  648.  
  649.                 LastPrintableColumn = LastColumn;
  650.  
  651.                 RepositionCursor();
  652.             }
  653.             else
  654.             {
  655.                 CursorX = LastPrintableColumn;
  656.  
  657.                 RepositionCursor();
  658.  
  659.                 return;
  660.             }
  661.         }
  662.  
  663.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  664.             Offset = Size;
  665.  
  666.         if(Config -> EmulationConfig -> InsertMode)
  667.         {
  668.             RasterShiftChar(Offset);
  669.  
  670.             ScrollLineShiftChar(Offset);
  671.  
  672.             ShiftChar(Offset);
  673.         }
  674.  
  675.         RasterPutString(Buffer,Offset);
  676.  
  677.         ScrollLinePutString(Offset);
  678.  
  679.         if(FontScalingRequired)
  680.             PrintScaled(Buffer,Offset,CurrentFontScale);
  681.         else
  682.             Text(RPort,Buffer,Offset);
  683.  
  684.         Buffer    += Offset;
  685.  
  686.         Size    -= Offset;
  687.  
  688.         CursorX    += Offset;
  689.     }
  690.  
  691.     RepositionCursor();
  692. }
  693.  
  694.     /* ConProcessUpdate():
  695.      *
  696.      *    Choose the right console data processing routine.
  697.      */
  698.  
  699. VOID
  700. ConProcessUpdate(VOID)
  701. {
  702.     Forbid();
  703.  
  704.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  705.     {
  706.         if(ReceiveTable)
  707.             ConProcessData = ConProcessDataTransExternal;
  708.         else
  709.             ConProcessData = ConProcessDataExternal;
  710.     }
  711.     else
  712.     {
  713.         if(Config -> SerialConfig -> StripBit8)
  714.         {
  715.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  716.                 ConProcessData = ConProcessDataHex7;
  717.             else
  718.                 ConProcessData = ConProcessData7;
  719.         }
  720.         else
  721.         {
  722.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  723.                 ConProcessData = ConProcessDataHex8;
  724.             else
  725.                 ConProcessData = ConProcessData8;
  726.         }
  727.     }
  728.  
  729.     Permit();
  730. }
  731.  
  732.     /* ConOutputUpdate():
  733.      *
  734.      *    Choose the right raw text output routine for the job.
  735.      */
  736.  
  737. VOID
  738. ConOutputUpdate()
  739. {
  740.     Forbid();
  741.  
  742.     if(BufferFrozen)
  743.     {
  744.         if(FileCapture)
  745.         {
  746.             if(PrinterCapture)
  747.             {
  748.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  749.                     CaptureData = CaptureFilteredTo_File_Printer;
  750.                 else
  751.                     CaptureData = CaptureRawTo_File_Printer;
  752.             }
  753.             else
  754.             {
  755.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  756.                     CaptureData = CaptureFilteredTo_File;
  757.                 else
  758.                     CaptureData = CaptureRawTo_File;
  759.             }
  760.         }
  761.         else
  762.         {
  763.             if(PrinterCapture)
  764.             {
  765.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  766.                     CaptureData = CaptureFilteredTo_Printer;
  767.                 else
  768.                     CaptureData = CaptureRawTo_Printer;
  769.             }
  770.             else
  771.                 CaptureData = NULL;
  772.         }
  773.     }
  774.     else
  775.     {
  776.         if(FileCapture)
  777.         {
  778.             if(PrinterCapture)
  779.             {
  780.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  781.                     CaptureData = CaptureFilteredTo_Buffer_File_Printer;
  782.                 else
  783.                     CaptureData = CaptureRawTo_Buffer_File_Printer;
  784.             }
  785.             else
  786.             {
  787.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  788.                     CaptureData = CaptureFilteredTo_Buffer_File;
  789.                 else
  790.                     CaptureData = CaptureRawTo_Buffer_File;
  791.             }
  792.         }
  793.         else
  794.         {
  795.             if(PrinterCapture)
  796.             {
  797.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  798.                     CaptureData = CaptureFilteredTo_Buffer_Printer;
  799.                 else
  800.                     CaptureData = CaptureRawTo_Buffer_Printer;
  801.             }
  802.             else
  803.             {
  804.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  805.                     CaptureData = CaptureFilteredTo_Buffer;
  806.                 else
  807.                     CaptureData = CaptureRawTo_Buffer;
  808.             }
  809.         }
  810.     }
  811.  
  812.     if(ControllerActive)
  813.         ConOutput = ConOutputPrinter;
  814.     else
  815.     {
  816.         if(CurrentFont == GFX)
  817.             ConOutput = ConOutputGFX;
  818.         else
  819.             ConOutput = ConOutputNormal;
  820.     }
  821.  
  822.     if(ReceiveTable)
  823.         ConDump = ConTransWrite;
  824.     else
  825.         ConDump = ConOutput;
  826.  
  827.     Permit();
  828. }
  829.  
  830.     /* ConFontScaleUpdate():
  831.      *
  832.      *    Choose the right font scale for the job.
  833.      */
  834.  
  835. VOID
  836. ConFontScaleUpdate()
  837. {
  838.     CurrentFontScale = RasterAttr[CursorY];
  839.  
  840.     if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  841.     {
  842.         FontScalingRequired    = (CurrentFontScale != SCALE_ATTR_2X);
  843.         LastPrintableColumn    = LastColumn;
  844.     }
  845.     else
  846.     {
  847.         if(FontScalingRequired = (CurrentFontScale != SCALE_ATTR_NORMAL))
  848.             LastPrintableColumn = ((LastColumn + 1) / 2) - 1;
  849.         else
  850.             LastPrintableColumn = LastColumn;
  851.     }
  852. }
  853.  
  854.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  855.      *
  856.      *    Frontend for ConWrite(), including character translation.
  857.      */
  858.  
  859. VOID
  860. ConTransWrite(STRPTR Buffer,LONG Size)
  861. {
  862.     struct TranslationHandle    Handle;
  863.     UBYTE                LocalBuffer[256];
  864.  
  865.         /* Set up for translation. */
  866.  
  867.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  868.  
  869.         /* Process and output the data. */
  870.  
  871.     while(Size = ConTranslateBuffer(&Handle))
  872.         (* ConOutput)(LocalBuffer,Size);
  873. }
  874.  
  875.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  876.      *
  877.      *    Process data, external emulation including translation flavour.
  878.      */
  879.  
  880. VOID
  881. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  882. {
  883.     struct TranslationHandle Handle;
  884.  
  885.         /* Set up for translation. */
  886.  
  887.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  888.  
  889.     if(StripBuffer)
  890.     {
  891.         register LONG Len;
  892.  
  893.             /* Process and output the data. */
  894.  
  895.         while(Size = ConTranslateBuffer(&Handle))
  896.         {
  897.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  898.  
  899.             XEM_HostData . Source        = ConTempBuffer;
  900.             XEM_HostData . Destination    = StripBuffer;
  901.  
  902.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  903.             {
  904.                 if(CaptureData)
  905.                     (*CaptureData)(StripBuffer,Len);
  906.             }
  907.         }
  908.     }
  909.     else
  910.     {
  911.             /* Process and output the data. */
  912.  
  913.         while(Size = ConTranslateBuffer(&Handle))
  914.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  915.     }
  916. }
  917.  
  918.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  919.      *
  920.      *    Process data, external emulation flavour.
  921.      */
  922.  
  923. VOID
  924. ConProcessDataExternal(register STRPTR String,register LONG Size)
  925. {
  926.     XEmulatorWrite(XEM_IO,String,Size);
  927.  
  928.         /* Build another string to contain
  929.          * the pure ASCII contents, i.e.
  930.          * not including any ESC control
  931.          * sequences.
  932.          */
  933.  
  934.     if(StripBuffer)
  935.     {
  936.         register LONG Len;
  937.  
  938.         XEM_HostData . Source        = String;
  939.         XEM_HostData . Destination    = StripBuffer;
  940.  
  941.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  942.         {
  943.             if(CaptureData)
  944.                 (*CaptureData)(StripBuffer,Len);
  945.         }
  946.     }
  947. }
  948.  
  949.     /* ConProcessData7(register STRPTR String,register LONG Size):
  950.      *
  951.      *    Process data, 7 bit flavour.
  952.      */
  953.  
  954. VOID
  955. ConProcessData7(register STRPTR String,register LONG Size)
  956. {
  957.     register LONG    Len = 0;
  958.     register UBYTE    c;
  959.  
  960.         // Check for prescroll/jump scroll
  961.  
  962.     if(CursorY == Bottom && Bottom > 0)
  963.     {
  964.             // The maximum number of line feeds we need to look for
  965.  
  966.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  967.  
  968.             // Any prescroll/jump scroll action wanted?
  969.  
  970.         if(Max)
  971.         {
  972.             register WORD     Count    = Size,
  973.                      Lines    = 0;
  974.             register UBYTE    *Buffer    = String;
  975.  
  976.                 // Count the number of line feeds
  977.  
  978.             while(Count--)
  979.             {
  980.                 if((*Buffer++ & 0x7F) == '\n')
  981.                 {
  982.                     if(++Lines == Max)
  983.                         break;
  984.                 }
  985.             }
  986.  
  987.                 // Ok, so we have found something
  988.  
  989.             if(Lines)
  990.             {
  991.                 register WORD Scroll,TotalLines;
  992.  
  993.                     // Scroll by default?
  994.  
  995.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  996.                 {
  997.                         // If there is more, use it
  998.  
  999.                     if(Lines > Scroll)
  1000.                         Scroll = Lines;
  1001.                 }
  1002.                 else
  1003.                     Scroll = Lines;
  1004.  
  1005.                     // How tall is the current scroll region?
  1006.  
  1007.                 TotalLines = Bottom - Top + 1;
  1008.  
  1009.                     // Don't scroll more than the entire screenful
  1010.  
  1011.                 if(Scroll > TotalLines)
  1012.                     Scroll = TotalLines;
  1013.  
  1014.                     // Is it worth scrolling?
  1015.  
  1016.                 if(Scroll > 1)
  1017.                 {
  1018.                     LONG OldBack = BackgroundPen;
  1019.  
  1020.                     if(OldBack)
  1021.                     {
  1022.                         BackgroundPen = 0;
  1023.  
  1024.                         UpdatePens();
  1025.                     }
  1026.  
  1027.                         // Scroll the region...
  1028.  
  1029.                     ScrollRegion(Scroll);
  1030.  
  1031.                         // Reposition the cursor
  1032.  
  1033.                     if(CursorY > Scroll)
  1034.                         CursorY -= Scroll;
  1035.                     else
  1036.                         CursorY = 0;
  1037.  
  1038.                     RepositionCursor();
  1039.  
  1040.                     if(OldBack)
  1041.                     {
  1042.                         BackgroundPen = OldBack;
  1043.  
  1044.                         UpdatePens();
  1045.                     }
  1046.                 }
  1047.             }
  1048.         }
  1049.     }
  1050.  
  1051.         /* If still parsing a sequence,
  1052.          * continue with it.
  1053.          */
  1054.  
  1055.     if(InSequence)
  1056.     {
  1057.         while(Size--)
  1058.         {
  1059.             c = *String++ & 0x7F;
  1060.  
  1061.             if(!(*AbortTable[c])(c))
  1062.             {
  1063.                 InSequence = FALSE;
  1064.  
  1065.                 break;
  1066.             }
  1067.         }
  1068.     }
  1069.  
  1070.         /* Check which font we are in, if other than Topaz
  1071.          * the only invalid char is a Null (0) which will
  1072.          * display as a space if let to continue.
  1073.          */
  1074.  
  1075.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1076.     {
  1077.         while(Size-- > 0)
  1078.         {
  1079.             if(IsPrintable[c = *String++ & 0x7F])
  1080.             {
  1081.                     /* This character is associated with a
  1082.                      * special function (bell, xon, xoff, etc.).
  1083.                      */
  1084.  
  1085.                 if(SpecialTable[c])
  1086.                 {
  1087.                     if(Len)
  1088.                     {
  1089.                         (*ConDump)(ConTempBuffer,Len);
  1090.  
  1091.                         Len = 0;
  1092.                     }
  1093.  
  1094.                         /* Does this character start
  1095.                          * a control sequence?
  1096.                          */
  1097.  
  1098.                     if(InSequence = (*SpecialTable[c])(c))
  1099.                     {
  1100.                         while(Size-- > 0)
  1101.                         {
  1102.                             c = *String++ & 0x7F;
  1103.  
  1104.                             if(!(*AbortTable[c])(c))
  1105.                             {
  1106.                                 InSequence = FALSE;
  1107.  
  1108.                                 break;
  1109.                             }
  1110.                         }
  1111.                     }
  1112.                 }
  1113.                 else
  1114.                 {
  1115.                         /* Put the character into the buffer
  1116.                          * and flush it if necessary.
  1117.                          */
  1118.  
  1119.                     ConTempBuffer[Len] = c;
  1120.  
  1121.                     if(Len++ == 512)
  1122.                     {
  1123.                         (*ConDump)(ConTempBuffer,Len);
  1124.  
  1125.                         Len = 0;
  1126.                     }
  1127.                 }
  1128.             }
  1129.         }
  1130.     }
  1131.     else
  1132.     {
  1133.         while(Size-- > 0)
  1134.         {
  1135.             if(c = (*String++ & 0x7F))
  1136.             {
  1137.                     /* This character is associated with a
  1138.                      * special function (bell, xon, xoff, etc.).
  1139.                      */
  1140.  
  1141.                 if(SpecialTable[c])
  1142.                 {
  1143.                     if(Len)
  1144.                     {
  1145.                         (*ConDump)(ConTempBuffer,Len);
  1146.  
  1147.                         Len = 0;
  1148.                     }
  1149.  
  1150.                     if(InSequence = (*SpecialTable[c])(c))
  1151.                     {
  1152.                         while(Size-- > 0)
  1153.                         {
  1154.                             c = *String++ & 0x7F;
  1155.  
  1156.                             if(!(*AbortTable[c])(c))
  1157.                             {
  1158.                                 InSequence = FALSE;
  1159.  
  1160.                                 break;
  1161.                             }
  1162.                         }
  1163.                     }
  1164.                 }
  1165.                 else
  1166.                 {
  1167.                         /* Put the character into the buffer
  1168.                          * and flush it if necessary.
  1169.                          */
  1170.  
  1171.                     ConTempBuffer[Len] = c;
  1172.  
  1173.                     if(Len++ == 512)
  1174.                     {
  1175.                         (*ConDump)(ConTempBuffer,Len);
  1176.  
  1177.                         Len = 0;
  1178.                     }
  1179.                 }
  1180.             }
  1181.         }
  1182.     }
  1183.  
  1184.     if(Len)
  1185.         (*ConDump)(ConTempBuffer,Len);
  1186. }
  1187.  
  1188.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1189.      *
  1190.      *    Process data, 8 bit flavour.
  1191.      */
  1192.  
  1193. VOID
  1194. ConProcessData8(register STRPTR String,register LONG Size)
  1195. {
  1196.     register LONG    Len = 0;
  1197.     register UBYTE    c;
  1198.  
  1199.         // Check for prescroll/jump scroll
  1200.  
  1201.     if(CursorY == Bottom && Bottom > 0)
  1202.     {
  1203.             // The maximum number of line feeds we need to look for
  1204.  
  1205.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  1206.  
  1207.             // Any prescroll/jump scroll action wanted?
  1208.  
  1209.         if(Max)
  1210.         {
  1211.             register WORD     Count    = Size,
  1212.                      Lines    = 0;
  1213.             register UBYTE    *Buffer    = String;
  1214.  
  1215.                 // Count the number of line feeds
  1216.  
  1217.             while(Count--)
  1218.             {
  1219.                 if(*Buffer++ == '\n')
  1220.                 {
  1221.                     if(++Lines == Max)
  1222.                         break;
  1223.                 }
  1224.             }
  1225.  
  1226.                 // Ok, so we have found something
  1227.  
  1228.             if(Lines)
  1229.             {
  1230.                 register WORD Scroll,TotalLines;
  1231.  
  1232.                     // Scroll by default?
  1233.  
  1234.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  1235.                 {
  1236.                         // If there is more, use it
  1237.  
  1238.                     if(Lines > Scroll)
  1239.                         Scroll = Lines;
  1240.                 }
  1241.                 else
  1242.                     Scroll = Lines;
  1243.  
  1244.                     // How tall is the current scroll region?
  1245.  
  1246.                 TotalLines = Bottom - Top + 1;
  1247.  
  1248.                     // Don't scroll more than the entire screenful
  1249.  
  1250.                 if(Scroll > TotalLines)
  1251.                     Scroll = TotalLines;
  1252.  
  1253.                     // Is it worth scrolling?
  1254.  
  1255.                 if(Scroll > 1)
  1256.                 {
  1257.                     LONG OldBack = BackgroundPen;
  1258.  
  1259.                     if(OldBack)
  1260.                     {
  1261.                         BackgroundPen = 0;
  1262.  
  1263.                         UpdatePens();
  1264.                     }
  1265.  
  1266.                         // Scroll the region...
  1267.  
  1268.                     ScrollRegion(Scroll);
  1269.  
  1270.                         // Reposition the cursor
  1271.  
  1272.                     if(CursorY > Scroll)
  1273.                         CursorY -= Scroll;
  1274.                     else
  1275.                         CursorY = 0;
  1276.  
  1277.                     RepositionCursor();
  1278.  
  1279.                     if(OldBack)
  1280.                     {
  1281.                         BackgroundPen = OldBack;
  1282.  
  1283.                         UpdatePens();
  1284.                     }
  1285.                 }
  1286.             }
  1287.         }
  1288.     }
  1289.  
  1290.     if(InSequence)
  1291.     {
  1292.         while(Size--)
  1293.         {
  1294.             c = *String++;
  1295.  
  1296.             if(!(*AbortTable[c])(c))
  1297.             {
  1298.                 InSequence = FALSE;
  1299.  
  1300.                 break;
  1301.             }
  1302.         }
  1303.     }
  1304.  
  1305.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1306.     {
  1307.         while(Size-- > 0)
  1308.         {
  1309.             if(IsPrintable[c = *String++])
  1310.             {
  1311.                 if(SpecialTable[c])
  1312.                 {
  1313.                     if(Len)
  1314.                     {
  1315.                         (*ConDump)(ConTempBuffer,Len);
  1316.  
  1317.                         Len = 0;
  1318.                     }
  1319.  
  1320.                     if(InSequence = (*SpecialTable[c])(c))
  1321.                     {
  1322.                         while(Size-- > 0)
  1323.                         {
  1324.                             c = *String++;
  1325.  
  1326.                             if(!(*AbortTable[c])(c))
  1327.                             {
  1328.                                 InSequence = FALSE;
  1329.  
  1330.                                 break;
  1331.                             }
  1332.                         }
  1333.                     }
  1334.                 }
  1335.                 else
  1336.                 {
  1337.                     ConTempBuffer[Len] = c;
  1338.  
  1339.                     if(Len++ == 512)
  1340.                     {
  1341.                         (*ConDump)(ConTempBuffer,Len);
  1342.  
  1343.                         Len = 0;
  1344.                     }
  1345.                 }
  1346.             }
  1347.         }
  1348.     }
  1349.     else
  1350.     {
  1351.         while(Size-- > 0)
  1352.         {
  1353.             if(c = *String++)
  1354.             {
  1355.                 if(SpecialTable[c])
  1356.                 {
  1357.                     if(Len)
  1358.                     {
  1359.                         (*ConDump)(ConTempBuffer,Len);
  1360.  
  1361.                         Len = 0;
  1362.                     }
  1363.  
  1364.                     if(InSequence = (*SpecialTable[c])(c))
  1365.                     {
  1366.                         while(Size-- > 0)
  1367.                         {
  1368.                             c = *String++;
  1369.  
  1370.                             if(!(*AbortTable[c])(c))
  1371.                             {
  1372.                                 InSequence = FALSE;
  1373.  
  1374.                                 break;
  1375.                             }
  1376.                         }
  1377.                     }
  1378.                 }
  1379.                 else
  1380.                 {
  1381.                     ConTempBuffer[Len] = c;
  1382.  
  1383.                     if(Len++ == 512)
  1384.                     {
  1385.                         (*ConDump)(ConTempBuffer,Len);
  1386.  
  1387.                         Len = 0;
  1388.                     }
  1389.                 }
  1390.             }
  1391.         }
  1392.     }
  1393.  
  1394.     if(Len)
  1395.         (*ConDump)(ConTempBuffer,Len);
  1396. }
  1397.  
  1398.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1399.      *
  1400.      *    Process data, hex mode flavour, seven bits.
  1401.      */
  1402.  
  1403. VOID
  1404. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1405. {
  1406.     UBYTE    DummyBuffer[40],c;
  1407.     LONG    Fit,Spaces,Current;
  1408.  
  1409.         /* How many characters will fit into the line? */
  1410.  
  1411.     Fit    = (LastColumn + 1) / 4;
  1412.  
  1413.         /* Which position are we currently in? */
  1414.  
  1415.     Current    = CursorX / 3;
  1416.  
  1417.         /* Weird cursor position? */
  1418.  
  1419.     if(Current >= Fit || (CursorX % 3))
  1420.     {
  1421.         ConProcessData7("\r\n",2);
  1422.  
  1423.         Current = 0;
  1424.     }
  1425.  
  1426.         /* Check the font type. */
  1427.  
  1428.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1429.     {
  1430.         while(Size-- > 0)
  1431.         {
  1432.             c = (*String++) & 0x7F;
  1433.  
  1434.             Spaces = (Fit - Current) * 3 + Current - 3;
  1435.  
  1436.             if(c > ' ' && c < 127)
  1437.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1438.             else
  1439.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1440.  
  1441.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1442.  
  1443.             if(Current++ == Fit - 1)
  1444.             {
  1445.                 Current = 0;
  1446.  
  1447.                 ConProcessData7("\r\n",2);
  1448.             }
  1449.         }
  1450.     }
  1451.     else
  1452.     {
  1453.         while(Size-- > 0)
  1454.         {
  1455.             c = (*String++) & 0x7F;
  1456.  
  1457.             Spaces = (Fit - Current) * 3 + Current - 3;
  1458.  
  1459.             if(c && c != ' ')
  1460.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1461.             else
  1462.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1463.  
  1464.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1465.  
  1466.             if(Current++ == Fit - 1)
  1467.             {
  1468.                 Current = 0;
  1469.  
  1470.                 ConProcessData7("\r\n",2);
  1471.             }
  1472.         }
  1473.     }
  1474. }
  1475.  
  1476.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1477.      *
  1478.      *    Process data, hex mode flavour, eight bits.
  1479.      */
  1480.  
  1481. VOID
  1482. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1483. {
  1484.     UBYTE    DummyBuffer[40],c;
  1485.     LONG    Fit,Spaces,Current;
  1486.  
  1487.         /* How many characters will fit into the line? */
  1488.  
  1489.     Fit    = (LastColumn + 1) / 4;
  1490.  
  1491.         /* Which position are we currently in? */
  1492.  
  1493.     Current    = CursorX / 3;
  1494.  
  1495.         /* Weird cursor position? */
  1496.  
  1497.     if(Current >= Fit || (CursorX % 3))
  1498.     {
  1499.         ConProcessData8("\r\n",2);
  1500.  
  1501.         Current = 0;
  1502.     }
  1503.  
  1504.         /* Check the font type. */
  1505.  
  1506.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1507.     {
  1508.         while(Size-- > 0)
  1509.         {
  1510.             c = *String++;
  1511.  
  1512.             Spaces = (Fit - Current) * 3 + Current - 3;
  1513.  
  1514.             if((c > ' ' && c < 127) || c > 160)
  1515.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1516.             else
  1517.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1518.  
  1519.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1520.  
  1521.             if(Current++ == Fit - 1)
  1522.             {
  1523.                 Current = 0;
  1524.  
  1525.                 ConProcessData8("\r\n",2);
  1526.             }
  1527.         }
  1528.     }
  1529.     else
  1530.     {
  1531.         while(Size-- > 0)
  1532.         {
  1533.             c = *String++;
  1534.  
  1535.             Spaces = (Fit - Current) * 3 + Current - 3;
  1536.  
  1537.             if(c && c != ' ')
  1538.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1539.             else
  1540.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1541.  
  1542.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1543.  
  1544.             if(Current++ == Fit - 1)
  1545.             {
  1546.                 Current = 0;
  1547.  
  1548.                 ConProcessData8("\r\n",2);
  1549.             }
  1550.         }
  1551.     }
  1552. }
  1553.  
  1554.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1555.      *
  1556.      *    Process data read from the serial line,
  1557.      *    special XPR flavour.
  1558.      */
  1559.  
  1560. VOID
  1561. ConTransferHost(STRPTR Buffer,LONG Len)
  1562. {
  1563.     Len = XProtocolHostMon(XprIO,Buffer,Len,SerialBufferSize);
  1564.  
  1565.     if(TransferWindow)
  1566.         TransferCleanup();
  1567.  
  1568.     if(Len)
  1569.         ConProcess(Buffer,Len);
  1570. }
  1571.  
  1572.     /* ConsoleCommand(STRPTR String):
  1573.      *
  1574.      *    Just like SerialCommand(), but addresses the local
  1575.      *    terminal side.
  1576.      */
  1577.  
  1578. VOID
  1579. ConsoleCommand(STRPTR String)
  1580. {
  1581.     STATIC UBYTE __far LocalBuffer[256];
  1582.  
  1583.     LONG    Count = 0,i,Len = strlen(String);
  1584.  
  1585.     BYTE    GotControl    = FALSE,
  1586.         GotEscape    = FALSE;
  1587.  
  1588.         /* Scan the string. */
  1589.  
  1590.     for(i = 0 ; i < Len ; i++)
  1591.     {
  1592.             /* We are looking for plain characters
  1593.              * and the control ('\') and escape
  1594.              * ('^') characters.
  1595.              */
  1596.  
  1597.         if(!GotControl && !GotEscape)
  1598.         {
  1599.                 /* Got a control character,
  1600.                  * the next byte will probably be
  1601.                  * a command sequence.
  1602.                  */
  1603.  
  1604.             if(String[i] == '\\')
  1605.             {
  1606.                 GotControl = TRUE;
  1607.  
  1608.                 continue;
  1609.             }
  1610.  
  1611.                 /* Got an escape character,
  1612.                  * the next byte will be some
  1613.                  * kind of control character
  1614.                  * (such as XON, XOF, bell, etc.).
  1615.                  */
  1616.  
  1617.             if(String[i] == '^')
  1618.             {
  1619.                 GotEscape = TRUE;
  1620.  
  1621.                 continue;
  1622.             }
  1623.  
  1624.                 /* This tells us to wait another
  1625.                  * second before continuing with
  1626.                  * the scanning.
  1627.                  */
  1628.  
  1629.             if(String[i] == '~')
  1630.                 continue;
  1631.  
  1632.                 /* Stuff the character into the
  1633.                  * buffer.
  1634.                  */
  1635.  
  1636.             LocalBuffer[Count++] = String[i];
  1637.         }
  1638.         else
  1639.         {
  1640.                 /* Convert the character to a control
  1641.                  * style character (^C, etc.).
  1642.                  */
  1643.  
  1644.             if(GotEscape)
  1645.             {
  1646.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1647.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1648.                 else
  1649.                     LocalBuffer[Count++] = String[i];
  1650.  
  1651.                 GotEscape = FALSE;
  1652.             }
  1653.  
  1654.                 /* The next character represents a command. */
  1655.  
  1656.             if(GotControl)
  1657.             {
  1658.                 switch(ToUpper(String[i]))
  1659.                 {
  1660.                         /* Translate code. */
  1661.  
  1662.                     case '*':
  1663.  
  1664.                         i++;
  1665.  
  1666.                         while(i < Len && String[i] == ' ')
  1667.                             i++;
  1668.  
  1669.                         if(i < Len)
  1670.                         {
  1671.                             UBYTE DummyBuffer[5],j = 0,Char;
  1672.  
  1673.                             if(String[i] >= '0' && String[i] <= '9')
  1674.                             {
  1675.                                 while(j < 3 && i < Len)
  1676.                                 {
  1677.                                     Char = String[i++];
  1678.  
  1679.                                     if(Char >= '0' && Char <= '9')
  1680.                                         DummyBuffer[j++] = Char;
  1681.                                     else
  1682.                                     {
  1683.                                         i--;
  1684.  
  1685.                                         break;
  1686.                                     }
  1687.                                 }
  1688.                             }
  1689.                             else
  1690.                             {
  1691.                                 while(j < 4 && i < Len)
  1692.                                 {
  1693.                                     Char = ToLower(String[i++]);
  1694.  
  1695.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1696.                                         DummyBuffer[j++] = Char;
  1697.                                     else
  1698.                                     {
  1699.                                         i--;
  1700.  
  1701.                                         break;
  1702.                                     }
  1703.                                 }
  1704.                             }
  1705.  
  1706.                             DummyBuffer[j] = 0;
  1707.  
  1708.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1709.                         }
  1710.  
  1711.                         i--;
  1712.  
  1713.                         break;
  1714.  
  1715.                         /* Execute an AmigaDOS command. */
  1716.  
  1717.                     case 'D':
  1718.  
  1719.                         return;
  1720.  
  1721.                         /* Execute an ARexx command. */
  1722.  
  1723.                     case 'A':
  1724.  
  1725.                         return;
  1726.  
  1727.                         /* Add the control character ('\'). */
  1728.  
  1729.                     case '\\':
  1730.  
  1731.                         LocalBuffer[Count++] = '\\';
  1732.                         break;
  1733.  
  1734.                         /* This is a backspace. */
  1735.  
  1736.                     case 'B':
  1737.  
  1738.                         LocalBuffer[Count++] = '\b';
  1739.                         break;
  1740.  
  1741.                         /* This is a form feed. */
  1742.  
  1743.                     case 'F':
  1744.  
  1745.                         LocalBuffer[Count++] = '\f';
  1746.                         break;
  1747.  
  1748.                         /* This is a line feed. */
  1749.  
  1750.                     case 'N':
  1751.  
  1752.                         LocalBuffer[Count++] = '\n';
  1753.                         break;
  1754.  
  1755.                         /* Send the current password. */
  1756.  
  1757.                     case 'P':
  1758.  
  1759.                         break;
  1760.  
  1761.                         /* This is a carriage return. */
  1762.  
  1763.                     case 'R':
  1764.  
  1765.                         LocalBuffer[Count++] = '\r';
  1766.                         break;
  1767.  
  1768.                         /* This is a tab. */
  1769.  
  1770.                     case 'T':
  1771.  
  1772.                         LocalBuffer[Count++] = '\t';
  1773.                         break;
  1774.  
  1775.                         /* Send the current user name. */
  1776.  
  1777.                     case 'U':
  1778.  
  1779.                         break;
  1780.  
  1781.                         /* Send a break across the serial line. */
  1782.  
  1783.                     case 'X':
  1784.  
  1785.                         break;
  1786.  
  1787.                         /* Feed the contents of the
  1788.                          * clipboard into the input
  1789.                          * stream.
  1790.                          */
  1791.  
  1792.                     case 'I':
  1793.  
  1794.                         if(Count)
  1795.                             ConProcess(LocalBuffer,Count);
  1796.  
  1797.                         Count = LoadClip(LocalBuffer,256);
  1798.  
  1799.                         break;
  1800.  
  1801.                         /* Send a string to the clipboard. */
  1802.  
  1803.                     case 'G':
  1804.  
  1805.                         if(String[i + 1])
  1806.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1807.  
  1808.                         return;
  1809.  
  1810.                         /* Produce the escape character. */
  1811.  
  1812.                     case 'E':
  1813.  
  1814.                         LocalBuffer[Count++] = ESC;
  1815.                         break;
  1816.  
  1817.                         /* Call a menu item. */
  1818.  
  1819.                     case 'C':
  1820.  
  1821.                         break;
  1822.  
  1823.                         /* Stuff the character into the buffer. */
  1824.  
  1825.                     default:
  1826.  
  1827.                         LocalBuffer[Count++] = String[i];
  1828.                         break;
  1829.                 }
  1830.  
  1831.                 GotControl = FALSE;
  1832.             }
  1833.         }
  1834.  
  1835.             /* If the buffer is full, release it. */
  1836.  
  1837.         if(Count == 256)
  1838.         {
  1839.             ConProcess(LocalBuffer,Count);
  1840.  
  1841.             Count = 0;
  1842.         }
  1843.     }
  1844.  
  1845.     if(Count)
  1846.         ConProcess(LocalBuffer,Count);
  1847. }
  1848.  
  1849.     /* ConBypass(STRPTR String,LONG Size):
  1850.      *
  1851.      *    Bypass the `normal' ConOutput() data processing.
  1852.      */
  1853.  
  1854. VOID __regargs
  1855. ConBypass(STRPTR String,LONG Size)
  1856. {
  1857.     if(Size < 0)
  1858.         Size = strlen(String);
  1859.  
  1860.     if(Size > 0)
  1861.     {
  1862.         VOID (* ProcessData)(STRPTR,LONG);
  1863.  
  1864.         if(Config -> SerialConfig -> StripBit8)
  1865.             ProcessData = ConProcessData7;
  1866.         else
  1867.             ProcessData = ConProcessData8;
  1868.  
  1869.         ObtainSemaphore(&TerminalSemaphore);
  1870.  
  1871.         if(Marking)
  1872.             DropMarker();
  1873.  
  1874.         ClearCursor();
  1875.  
  1876.         (*ProcessData)(String,Size);
  1877.  
  1878.         DrawCursor();
  1879.  
  1880.         ReleaseSemaphore(&TerminalSemaphore);
  1881.     }
  1882. }
  1883.  
  1884.     /* ConProcess(STRPTR String,LONG Size):
  1885.      *
  1886.      *    Process the contents of a string to be sent to the
  1887.      *    console window.
  1888.      */
  1889.  
  1890. VOID
  1891. ConProcess(register STRPTR String,register LONG Size)
  1892. {
  1893.         /* Feed the flow filter. */
  1894.  
  1895.     if(UseFlow)
  1896.     {
  1897.         if(Config -> SerialConfig -> StripBit8)
  1898.             FlowFilter(String,Size,0x7F);
  1899.         else
  1900.             FlowFilter(String,Size,0xFF);
  1901.     }
  1902.  
  1903.         /* In quiet mode no characters are echoed to the
  1904.          * console window, they are just passed through
  1905.          * the data flow filter. Usually, this mode is
  1906.          * enabled by the dial panel.
  1907.          */
  1908.  
  1909.     if(!Quiet)
  1910.     {
  1911.             /* Capture the data. */
  1912.  
  1913.         if(CaptureData && Size > 0)
  1914.         {
  1915.             if(Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  1916.             {
  1917.                 UBYTE     LocalBuffer[BUFFER_LINE_MAX];
  1918.  
  1919.                 UBYTE    *Src = String,
  1920.                     *Dst,
  1921.                      c;
  1922.  
  1923.                 ULONG     Count,Len = Size;
  1924.  
  1925.                 while(Len > 0)
  1926.                 {
  1927.                     Count = MIN(BUFFER_LINE_MAX,Len);
  1928.  
  1929.                     Len -= Count;
  1930.  
  1931.                     Dst = LocalBuffer;
  1932.  
  1933.                     do
  1934.                     {
  1935.                         if(c = ISOConversion[*Src++])
  1936.                             *Dst++ = c;
  1937.                         else
  1938.                             *Dst++ = (UBYTE)'·';
  1939.                     }
  1940.                     while(--Count > 0);
  1941.  
  1942.                     if((Count = (ULONG)Dst - (ULONG)&LocalBuffer[0]) > 0)
  1943.                         (*CaptureData)(LocalBuffer,Count);
  1944.                 }
  1945.             }
  1946.             else
  1947.                 (*CaptureData)(String,Size);
  1948.         }
  1949.  
  1950.             /* Remember the data. */
  1951.  
  1952.         if(RememberOutput)
  1953.             RememberOutputText(String,Size);
  1954.  
  1955.             /* Check the traps if necessary. */
  1956.  
  1957.         if(WatchTraps)
  1958.             TrapFilter(String,Size);
  1959.  
  1960.         if(Marking)
  1961.             DropMarker();
  1962.  
  1963.         if(TerminalQueue)
  1964.         {
  1965.             struct DataMsg *Msg;
  1966.  
  1967.             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + Size))
  1968.             {
  1969.                 Msg -> Data = (APTR)(Msg + 1);
  1970.                 Msg -> Size = Size;
  1971.  
  1972.                 CopyMem(String,Msg -> Data,Msg -> Size);
  1973.  
  1974.                 PutMsgItem(TerminalQueue,Msg);
  1975.             }
  1976.             else
  1977.             {
  1978.                 ClearCursor();
  1979.  
  1980.                 (*ConProcessData)(String,Size);
  1981.  
  1982.                 DrawCursor();
  1983.             }
  1984.         }
  1985.         else
  1986.         {
  1987.             ClearCursor();
  1988.  
  1989.             (*ConProcessData)(String,Size);
  1990.  
  1991.             DrawCursor();
  1992.         }
  1993.     }
  1994. }
  1995.  
  1996.     /* ConWrites(STRPTR String,...):
  1997.      *
  1998.      *    Output a string to the console.
  1999.      */
  2000.  
  2001. VOID __stdargs
  2002. ConWrites(STRPTR String,...)
  2003. {
  2004.     va_list    VarArgs;
  2005.  
  2006.     if(Marking)
  2007.         DropMarker();
  2008.  
  2009.     va_start(VarArgs,String);
  2010.     VSPrintf(SharedBuffer,String,VarArgs);
  2011.     va_end(VarArgs);
  2012.  
  2013.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  2014. }
  2015.  
  2016.     /* FlowInit():
  2017.      *
  2018.      *    Set up the data flow parser. The parser scans the serial
  2019.      *    output data for more or less interesting modem output
  2020.      *    (carrier lost, connect, etc.).
  2021.      */
  2022.  
  2023. VOID __regargs
  2024. FlowInit(BYTE FullReset)
  2025. {
  2026.     WORD i;
  2027.  
  2028.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2029.         AttentionBuffers[i][0] = 0;
  2030.  
  2031.         /* Set up `NO CARRIER' message. */
  2032.  
  2033.     if(Config -> ModemConfig -> NoCarrier[0])
  2034.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  2035.  
  2036.         /* Set up ZRQINIT message. */
  2037.  
  2038. //    strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
  2039.  
  2040.         /* Set up `CONNECT' message. */
  2041.  
  2042.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  2043.  
  2044.         /* Set up `VOICE' message. */
  2045.  
  2046.     if(Config -> ModemConfig -> Voice[0])
  2047.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  2048.  
  2049.         /* Set up `RING' message. */
  2050.  
  2051.     if(Config -> ModemConfig -> Ring[0])
  2052.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  2053.  
  2054.         /* Set up `BUSY' message. */
  2055.  
  2056.     if(Config -> ModemConfig -> Busy[0])
  2057.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  2058.  
  2059.         /* Set up `NO DIALTONE' message. */
  2060.  
  2061.     if(Config -> ModemConfig -> NoDialTone[0])
  2062.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  2063.  
  2064.         /* Set up `OK' message. */
  2065.  
  2066.     if(Config -> ModemConfig -> Ok[0])
  2067.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  2068.  
  2069.         /* Set up `ERROR' message. */
  2070.  
  2071.     if(Config -> ModemConfig -> Error[0])
  2072.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  2073.  
  2074.         /* Reset match counter. */
  2075.  
  2076.     FlowCount = 0;
  2077.  
  2078.         /* Reset indices. */
  2079.  
  2080.     memset(AttentionCount,0,sizeof(AttentionCount));
  2081.  
  2082.         /* Determine lengths. */
  2083.  
  2084.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2085.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  2086.  
  2087.     for(i = SCAN_SIGDEFAULTUPLOAD ; i <= SCAN_SIGBINARYDOWNLOAD ; i++)
  2088.     {
  2089.         if(AttentionLength[i] = Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length)
  2090.             memcpy(AttentionBuffers[i],Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Signature,Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length);
  2091.     }
  2092.  
  2093.     if(Config -> TransferConfig -> ASCIIUploadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  2094.         AttentionLength[SCAN_SIGASCIIUPLOAD] = 0;
  2095.  
  2096.     if(Config -> TransferConfig -> ASCIIDownloadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  2097.         AttentionLength[SCAN_SIGASCIIDOWNLOAD] = 0;
  2098.  
  2099.     if(Config -> TransferConfig -> TextUploadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  2100.         AttentionLength[SCAN_SIGTEXTUPLOAD] = 0;
  2101.  
  2102.     if(Config -> TransferConfig -> TextDownloadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  2103.         AttentionLength[SCAN_SIGTEXTDOWNLOAD] = 0;
  2104.  
  2105.     if(Config -> TransferConfig -> BinaryUploadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  2106.         AttentionLength[SCAN_SIGBINARYUPLOAD] = 0;
  2107.  
  2108.     if(Config -> TransferConfig -> BinaryDownloadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  2109.         AttentionLength[SCAN_SIGBINARYDOWNLOAD] = 0;
  2110.  
  2111.     if(FullReset)
  2112.     {
  2113.             /* No, we are not yet looking for a baud rate. */
  2114.  
  2115.         BaudPending = FALSE;
  2116.  
  2117.             /* Reset the flags. */
  2118.  
  2119.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  2120.     }
  2121.  
  2122.         /* Full data check is a lot slower than looking for
  2123.          * just a single sequence (such as the `CONNECT'
  2124.          * below). This mode is reserved for the dial panel.
  2125.          */
  2126.  
  2127.     ScanStart    = 0;
  2128.     ScanEnd        = SCAN_COUNT - 1;
  2129.     UseFlow        = TRUE;
  2130. }
  2131.  
  2132.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  2133.      *
  2134.      *    Text output, if necessary switching from gfx font
  2135.      *    to current default font.
  2136.      */
  2137.  
  2138. VOID __regargs
  2139. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  2140. {
  2141.     BYTE TextMode;
  2142.     LONG SameMode;
  2143.  
  2144.         /* Determine current text rendering mode. */
  2145.  
  2146.     if(GfxTable[Buffer[0]] == MODE_GFX)
  2147.         TextMode = MODE_GFX;
  2148.     else
  2149.     {
  2150.         TextMode = MODE_STANDARD;
  2151.  
  2152.         SetFont(RPort,TextFont);
  2153.     }
  2154.  
  2155.         /* Reset number of characters in common mode. */
  2156.  
  2157.     SameMode = 0;
  2158.  
  2159.         /* Scan until all input is processed. */
  2160.  
  2161.     FOREVER
  2162.     {
  2163.             /* Scan for characters in the current mode. */
  2164.  
  2165.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  2166.             SameMode++;
  2167.  
  2168.             /* Output the text found. */
  2169.  
  2170.         Text(RPort,Buffer,SameMode);
  2171.  
  2172.             /* Decrement number of remaining bytes. */
  2173.  
  2174.         Length -= SameMode;
  2175.  
  2176.             /* Anything left? */
  2177.  
  2178.         if(Length)
  2179.         {
  2180.                 /* Skip to next character. */
  2181.  
  2182.             Buffer        += SameMode;
  2183.             SameMode     = 0;
  2184.  
  2185.                 /* Change text output mode. */
  2186.  
  2187.             if(TextMode == MODE_GFX)
  2188.             {
  2189.                 SetFont(RPort,TextFont);
  2190.  
  2191.                 TextMode = MODE_STANDARD;
  2192.             }
  2193.             else
  2194.             {
  2195.                 SetFont(RPort,GFX);
  2196.  
  2197.                 TextMode = MODE_GFX;
  2198.             }
  2199.         }
  2200.         else
  2201.             break;
  2202.     }
  2203.  
  2204.         /* Reset font type. */
  2205.  
  2206.     if(TextMode == MODE_STANDARD)
  2207.         SetFont(RPort,GFX);
  2208. }
  2209.  
  2210.     /* ConvertKey():
  2211.      *
  2212.      *    The actual key conversion routine.
  2213.      */
  2214.  
  2215. STATIC LONG __inline
  2216. ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
  2217. {
  2218.     LONG Actual;
  2219.  
  2220.         /* Fill in the defaults. */
  2221.  
  2222.     FakeInputEvent -> ie_Code        = Code;
  2223.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  2224.     FakeInputEvent -> ie_position . ie_addr    = (APTR)Prev;
  2225.  
  2226.         /* Clear the buffer (sortof). */
  2227.  
  2228.     Buffer[0] = 0;
  2229.  
  2230.         /* Convert the codes. */
  2231.  
  2232.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  2233.         return(Actual);
  2234.     else
  2235.         return(0);
  2236. }
  2237.  
  2238.     /* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
  2239.      *
  2240.      *    Much more simplified raw key conversion routine.
  2241.      */
  2242.  
  2243. UBYTE __regargs
  2244. ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
  2245. {
  2246.     if(Buffer)
  2247.         Buffer[0] = 0;
  2248.  
  2249.     if(Len)
  2250.         *Len = 0;
  2251.  
  2252.         /* Key was pressed, not released. */
  2253.  
  2254.     if(!(Code & IECODE_UP_PREFIX))
  2255.     {
  2256.             /* These are the sequences mapped to special
  2257.              * control keys (cursor keys, function keys,
  2258.              * the help key).
  2259.              */
  2260.  
  2261.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2262.         {
  2263.             (STRPTR)"A",    CUP,
  2264.             (STRPTR)"B",    CDN,
  2265.             (STRPTR)"C",    CFW,
  2266.             (STRPTR)"D",    CBK,
  2267.  
  2268.             (STRPTR)"?~",    HLP,
  2269.  
  2270.             (STRPTR)"0~",    FN1,
  2271.             (STRPTR)"1~",    FN2,
  2272.             (STRPTR)"2~",    FN3,
  2273.             (STRPTR)"3~",    FN4,
  2274.             (STRPTR)"4~",    FN5,
  2275.             (STRPTR)"5~",    FN6,
  2276.             (STRPTR)"6~",    FN7,
  2277.             (STRPTR)"7~",    FN8,
  2278.             (STRPTR)"8~",    FN9,
  2279.             (STRPTR)"9~",    F10
  2280.         };
  2281.  
  2282.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2283.  
  2284.         UBYTE    ConvertBuffer[257];
  2285.         LONG    Actual;
  2286.  
  2287.             /* If it's a function or cursor key, clear the qualifier. */
  2288.  
  2289.         if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
  2290.             Qualifier = NULL;
  2291.         else
  2292.         {
  2293.                 /* Does it have a numeric keypad qualifier set? */
  2294.  
  2295.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2296.             {
  2297.                 STRPTR String = NULL;
  2298.  
  2299.                     /* Look at the vanilla result. */
  2300.  
  2301.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
  2302.                 {
  2303.                         /* Take a look at the results. */
  2304.  
  2305.                     switch(ConvertBuffer[0])
  2306.                     {
  2307.                         case '(':
  2308.                         case '[':
  2309.                         case '{':
  2310.  
  2311.                             String = "\033OP";
  2312.                             break;
  2313.  
  2314.                         case ')':
  2315.                         case ']':
  2316.                         case '}':
  2317.  
  2318.                             String = "\033OQ";
  2319.                             break;
  2320.  
  2321.                         case '/':
  2322.  
  2323.                             String = "\033OR";
  2324.                             break;
  2325.  
  2326.                         case '*':
  2327.  
  2328.                             String = "\033OS";
  2329.                             break;
  2330.  
  2331.                         default:
  2332.  
  2333.                             String = NULL;
  2334.                             break;
  2335.                     }
  2336.                 }
  2337.  
  2338.                 if(!String)
  2339.                 {
  2340.                     switch(Code)
  2341.                     {
  2342.                         case 0x5A:
  2343.  
  2344.                             String = "\033OP";
  2345.                             break;
  2346.  
  2347.                         case 0x5B:
  2348.  
  2349.                             String = "\033OQ";
  2350.                             break;
  2351.  
  2352.                         case 0x5C:
  2353.  
  2354.                             String = "\033OR";
  2355.                             break;
  2356.  
  2357.                         case 0x5D:
  2358.  
  2359.                             String = "\033OS";
  2360.                             break;
  2361.                     }
  2362.                 }
  2363.  
  2364.                     /* Return the PFx key code. */
  2365.  
  2366.                 if(String)
  2367.                 {
  2368.                     if(Buffer)
  2369.                         memcpy(Buffer,String,3);
  2370.  
  2371.                     if(Len)
  2372.                         *Len = 3;
  2373.  
  2374.                     return('\033');
  2375.                 }
  2376.             }
  2377.  
  2378.                 /* Does it have a shift qualifier set? */
  2379.  
  2380.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2381.             {
  2382.                     /* Do the conversion... */
  2383.  
  2384.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
  2385.                 {
  2386.                         /* Did it produce a tab key? If so, transfer
  2387.                          * Esc tab instead.
  2388.                          */
  2389.  
  2390.                     if(ConvertBuffer[0] == '\t')
  2391.                     {
  2392.                         if(Len)
  2393.                             *Len = 2;
  2394.  
  2395.                         if(Buffer)
  2396.                             memcpy(Buffer,"\033\t",2);
  2397.  
  2398.                         return('\033');
  2399.                     }
  2400.                 }
  2401.             }
  2402.  
  2403.                 /* Does it have the control qualifier set? */
  2404.  
  2405.             if(Qualifier & IEQUALIFIER_CONTROL)
  2406.             {
  2407.                     /* Do the conversion... */
  2408.  
  2409.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
  2410.                 {
  2411.                         /* Did it produce a space or an `at' sign? */
  2412.  
  2413.                     switch(ConvertBuffer[0])
  2414.                     {
  2415.                             /* NUL */
  2416.  
  2417.                         case ' ':
  2418.                         case '@':
  2419.                         case '2':
  2420.  
  2421.                             if(Len)
  2422.                                 *Len = 1;
  2423.  
  2424.                             if(Buffer)
  2425.                                 Buffer[0] = 0;
  2426.  
  2427.                             return(0);
  2428.  
  2429.                             /* Escape */
  2430.  
  2431.                         case '3':
  2432.                         case '[':
  2433.  
  2434.                             if(Len)
  2435.                                 *Len = 1;
  2436.  
  2437.                             if(Buffer)
  2438.                                 Buffer[0] = 0x1B;
  2439.  
  2440.                             return(0x1B);
  2441.  
  2442.                             /* FS */
  2443.  
  2444.                         case '4':
  2445.                         case '/':
  2446.  
  2447.                             if(Len)
  2448.                                 *Len = 1;
  2449.  
  2450.                             if(Buffer)
  2451.                                 Buffer[0] = 0x1C;
  2452.  
  2453.                             return(0x1C);
  2454.  
  2455.                             /* GS */
  2456.  
  2457.                         case '5':
  2458.                         case ']':
  2459.  
  2460.                             if(Len)
  2461.                                 *Len = 1;
  2462.  
  2463.                             if(Buffer)
  2464.                                 Buffer[0] = 0x1D;
  2465.  
  2466.                             return(0x1D);
  2467.  
  2468.                             /* RS */
  2469.  
  2470.                         case '6':
  2471.                         case '~':
  2472.  
  2473.                             if(Len)
  2474.                                 *Len = 1;
  2475.  
  2476.                             if(Buffer)
  2477.                                 Buffer[0] = 0x1E;
  2478.  
  2479.                             return(0x1E);
  2480.  
  2481.  
  2482.                             /* US */
  2483.  
  2484.                         case '7':
  2485.                         case '?':
  2486.  
  2487.                             if(Len)
  2488.                                 *Len = 1;
  2489.  
  2490.                             if(Buffer)
  2491.                                 Buffer[0] = 0x1F;
  2492.  
  2493.                             return(0x1F);
  2494.                     }
  2495.                 }
  2496.             }
  2497.         }
  2498.  
  2499.             /* Do the final conversion... */
  2500.  
  2501.         if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
  2502.         {
  2503.                 /* Are we to swap the backspace and
  2504.                  * delete keys?
  2505.                  */
  2506.  
  2507.             if(Config -> EmulationConfig -> SwapBSDelete)
  2508.             {
  2509.                 register WORD i;
  2510.  
  2511.                 for(i = 0 ; i < Actual ; i++)
  2512.                 {
  2513.                     if(ConvertBuffer[i] == BKS)
  2514.                         ConvertBuffer[i] = DEL;
  2515.                     else
  2516.                     {
  2517.                         if(ConvertBuffer[i] == DEL)
  2518.                             ConvertBuffer[i] = BKS;
  2519.                     }
  2520.                 }
  2521.             }
  2522.  
  2523.                 /* Translated sequence starts
  2524.                  * with a CSI, let's have a look
  2525.                  * at the associated control
  2526.                  * key.
  2527.                  */
  2528.  
  2529.             if(ConvertBuffer[0] == CSI)
  2530.             {
  2531.                 register WORD i;
  2532.  
  2533.                 for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2534.                 {
  2535.                         /* Does it match? */
  2536.  
  2537.                     if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2538.                     {
  2539.                             /* Store the length. */
  2540.  
  2541.                         if(Len)
  2542.                             *Len = 1;
  2543.  
  2544.                             /* Store the result. */
  2545.  
  2546.                         if(Buffer)
  2547.                         {
  2548.                             Buffer[0] = ConversionTable[i] . Result;
  2549.                             Buffer[1] = 0;
  2550.                         }
  2551.  
  2552.                         return(ConversionTable[i] . Result);
  2553.                     }
  2554.                 }
  2555.             }
  2556.  
  2557.                 /* Store the number of characters converted. */
  2558.  
  2559.             if(Len)
  2560.                 *Len = Actual;
  2561.  
  2562.                 /* Store the converted characters. */
  2563.  
  2564.             if(Buffer)
  2565.                 memcpy(Buffer,ConvertBuffer,Actual);
  2566.  
  2567.             return(ConvertBuffer[0]);
  2568.         }
  2569.     }
  2570.  
  2571.     return(0);
  2572. }
  2573.  
  2574.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2575.      *
  2576.      *    Convert a raw key information according to the
  2577.      *    current keymap settings.
  2578.      */
  2579.  
  2580. UBYTE __regargs
  2581. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2582. {
  2583.         /* Is this really a keyboard event? */
  2584.  
  2585.     if(Massage -> Class == IDCMP_RAWKEY)
  2586.         return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
  2587.     else
  2588.     {
  2589.         if(Buffer)
  2590.             Buffer[0] = 0;
  2591.  
  2592.         if(Len)
  2593.             *Len = 0;
  2594.  
  2595.         return(0);
  2596.     }
  2597. }
  2598.  
  2599.     /* DoBackspace():
  2600.      *
  2601.      *    Special function: perform backspace.
  2602.      */
  2603.  
  2604. BYTE
  2605. DoBackspace()
  2606. {
  2607.     if(CursorX)
  2608.     {
  2609.         WORD DeltaX,MinX;
  2610.  
  2611.         CursorX--;
  2612.  
  2613.             // What backspace mode are we in?
  2614.  
  2615.         switch(Config -> EmulationConfig -> DestructiveBackspace)
  2616.         {
  2617.                 // Do nothing
  2618.  
  2619.             case 0:
  2620.  
  2621.                 RepositionCursor();
  2622.                 break;
  2623.  
  2624.                 // Shift the line to the left
  2625.  
  2626.             case 2:
  2627.  
  2628.                 BackupRender();
  2629.  
  2630.                 RasterEraseCharacters(1);
  2631.  
  2632.                 if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
  2633.                 {
  2634.                     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2635.                     {
  2636.                         DeltaX    = TextFontWidth;
  2637.                         MinX    = MUL_X(CursorX);
  2638.                     }
  2639.                     else
  2640.                     {
  2641.                         DeltaX    = TextFontWidth / 2;
  2642.                         MinX    = MUL_X(CursorX) / 2;
  2643.                     }
  2644.                 }
  2645.                 else
  2646.                 {
  2647.                     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2648.                     {
  2649.                         DeltaX    = TextFontWidth / 2;
  2650.                         MinX    = MUL_X(CursorX) / 2;
  2651.                     }
  2652.                     else
  2653.                     {
  2654.                         DeltaX    = TextFontWidth;
  2655.                         MinX    = MUL_X(CursorX);
  2656.                     }
  2657.                 }
  2658.  
  2659.                 ScrollLineEraseCharacters(1);
  2660.  
  2661.                 ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2662.  
  2663.                 BackupRender();
  2664.  
  2665.                 RepositionCursor();
  2666.  
  2667.                 break;
  2668.  
  2669.                 // Clear the character below the cursor
  2670.  
  2671.             default:
  2672.  
  2673.                 RepositionCursor();
  2674.  
  2675.                 ObtainSemaphore(RasterSemaphore);
  2676.  
  2677.                 Raster[CursorY * RasterWidth + CursorX] = ' ';
  2678.  
  2679.                 ReleaseSemaphore(RasterSemaphore);
  2680.  
  2681.                 BackupRender();
  2682.  
  2683.                 if(FontScalingRequired)
  2684.                     PrintScaled(" ",1,CurrentFontScale);
  2685.                 else
  2686.                     Text(RPort," ",1);
  2687.  
  2688.                 BackupRender();
  2689.  
  2690.                 break;
  2691.         }
  2692.     }
  2693.  
  2694.     return(FALSE);
  2695. }
  2696.  
  2697.     /* DoBeep():
  2698.      *
  2699.      *    The real interface to the beep routine.
  2700.      */
  2701.  
  2702. BYTE
  2703. DoBeep()
  2704. {
  2705.     BellSignal();
  2706.  
  2707.     return(FALSE);
  2708. }
  2709.  
  2710.     /* DoxON():
  2711.      *
  2712.      *    Perform XON (stop data flow).
  2713.      */
  2714.  
  2715. BYTE
  2716. DoxON()
  2717. {
  2718.         // Commented out, `term' now handles xON locally only
  2719.  
  2720. //    if(Config -> SerialConfig -> xONxOFF)
  2721. //        Status = STATUS_HOLDING;
  2722.  
  2723.     return(FALSE);
  2724. }
  2725.  
  2726.     /* DoLF():
  2727.      *
  2728.      *    Special function: perform line feed.
  2729.      */
  2730.  
  2731. BYTE
  2732. DoLF()
  2733. {
  2734.     DownLine();
  2735.  
  2736.     RepositionCursor();
  2737.  
  2738.     return(FALSE);
  2739. }
  2740.  
  2741.     /* DoShiftIn():
  2742.      *
  2743.      *    Special function: Shift into graphics mode
  2744.      */
  2745.  
  2746. BYTE
  2747. DoShiftIn()
  2748. {
  2749.     if(CharMode[1] == TABLE_GFX && GFX)
  2750.         CurrentFont = GFX;
  2751.  
  2752.     if(CharMode[1] == TABLE_ASCII)
  2753.         CurrentFont = TextFont;
  2754.  
  2755.     SetFont(RPort,CurrentFont);
  2756.  
  2757.     ConOutputUpdate();
  2758.  
  2759.     Charset = 1;
  2760.  
  2761.     return(FALSE);
  2762. }
  2763.  
  2764.     /* DoShiftOut():
  2765.      *
  2766.      *    Special function: Shift out of graphics mode
  2767.      */
  2768.  
  2769. BYTE
  2770. DoShiftOut()
  2771. {
  2772.     if(CharMode[0] == TABLE_GFX && GFX)
  2773.         CurrentFont = GFX;
  2774.  
  2775.     if(CharMode[0] == TABLE_ASCII)
  2776.         CurrentFont = TextFont;
  2777.  
  2778.     SetFont(RPort,CurrentFont);
  2779.  
  2780.     ConOutputUpdate();
  2781.  
  2782.     Charset = 0;
  2783.  
  2784.     return(FALSE);
  2785. }
  2786.  
  2787.     /* DoCR_LF():
  2788.      *
  2789.      *    Special function: perform carriage return and line feed.
  2790.      */
  2791.  
  2792. BYTE
  2793. DoCR_LF()
  2794. {
  2795.     CursorX = 0;
  2796.  
  2797.     DownLine();
  2798.  
  2799.     RepositionCursor();
  2800.  
  2801.     return(FALSE);
  2802. }
  2803.  
  2804.     /* DoFF():
  2805.      *
  2806.      *    Special function: perform form feed.
  2807.      */
  2808.  
  2809. BYTE
  2810. DoFF()
  2811. {
  2812.     if(Config -> EmulationConfig -> NewLineMode)
  2813.     {
  2814.         CursorX = 0;
  2815.  
  2816.         DoCR_LF();
  2817.     }
  2818.     else
  2819.     {
  2820.         EraseScreen("2");
  2821.  
  2822.         CursorX = CursorY = 0;
  2823.  
  2824.         RepositionCursor();
  2825.  
  2826.         ConFontScaleUpdate();
  2827.     }
  2828.  
  2829.     return(FALSE);
  2830. }
  2831.  
  2832.     /* DoLF_FF_VT():
  2833.      *
  2834.      *    Special function: handle line feed, form feed and vertical
  2835.      *    tab.
  2836.      */
  2837.  
  2838. BYTE
  2839. DoLF_FF_VT()
  2840. {
  2841.     if(Config -> EmulationConfig -> NewLineMode)
  2842.         DoCR_LF();
  2843.     else
  2844.         DoLF();
  2845.  
  2846.     return(FALSE);
  2847. }
  2848.  
  2849.     /* DoCR():
  2850.      *
  2851.      *    Special function: handle carriage return.
  2852.      */
  2853.  
  2854. BYTE
  2855. DoCR()
  2856. {
  2857.     if(Config -> EmulationConfig -> NewLineMode)
  2858.         DoCR_LF();
  2859.     else
  2860.     {
  2861.         CursorX = 0;
  2862.  
  2863.         RepositionCursor();
  2864.     }
  2865.  
  2866.     return(FALSE);
  2867. }
  2868.  
  2869.     /* DoTab():
  2870.      *
  2871.      *    Special function: handle tab, move cursor to next
  2872.      *    tab stop.
  2873.      */
  2874.  
  2875. BYTE
  2876. DoTab()
  2877. {
  2878.     WORD Column;
  2879.  
  2880.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2881.         Column = LastColumn;
  2882.     else
  2883.         Column = ((LastColumn + 1) / 2) - 1;
  2884.  
  2885.     if(Config -> EmulationConfig -> LineWrap)
  2886.     {
  2887.         if(CursorX >= LastColumn)
  2888.         {
  2889.             CursorX = 0;
  2890.  
  2891.             DownLine();
  2892.         }
  2893.         else
  2894.         {
  2895.             while(CursorX < Column)
  2896.             {
  2897.                 CursorX++;
  2898.  
  2899.                 if(TabStops[CursorX])
  2900.                     break;
  2901.             }
  2902.         }
  2903.     }
  2904.     else
  2905.     {
  2906.         while(CursorX < Column)
  2907.         {
  2908.             CursorX++;
  2909.  
  2910.             if(TabStops[CursorX])
  2911.                 break;
  2912.         }
  2913.     }
  2914.  
  2915.     RepositionCursor();
  2916.  
  2917.     return(FALSE);
  2918. }
  2919.  
  2920.     /* DoEnq():
  2921.      *
  2922.      *    Special function: send answerback message.
  2923.      */
  2924.  
  2925. BYTE
  2926. DoEnq()
  2927. {
  2928.     if(Config -> EmulationConfig -> AnswerBack[0])
  2929.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  2930.  
  2931.     return(FALSE);
  2932. }
  2933.  
  2934.     /* DoEsc():
  2935.      *
  2936.      *    Start new control sequence.
  2937.      */
  2938.  
  2939. BYTE
  2940. DoEsc()
  2941. {
  2942.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2943.         (* ConDump)("^",1);
  2944.  
  2945.     return(TRUE);
  2946. }
  2947.  
  2948.     /* DoCsi():
  2949.      *
  2950.      *    Start new control sequence.
  2951.      */
  2952.  
  2953. BYTE
  2954. DoCsi()
  2955. {
  2956.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2957.         (* ConDump)("^[",2);
  2958.  
  2959.     ParseCode('[');
  2960.  
  2961.     return(TRUE);
  2962. }
  2963.  
  2964.     /* DoNewEsc(UBYTE Char):
  2965.      *
  2966.      *    Start new control sequence.
  2967.      */
  2968.  
  2969. BYTE
  2970. DoNewEsc(UBYTE Char)
  2971. {
  2972.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2973.         (* ConDump)("^",1);
  2974.  
  2975.     DoCancel();
  2976.  
  2977.     InSequence = TRUE;
  2978.  
  2979.     return(TRUE);
  2980. }
  2981.  
  2982.     /* DoNewCsi(UBYTE Char):
  2983.      *
  2984.      *    Start new control sequence.
  2985.      */
  2986.  
  2987. BYTE
  2988. DoNewCsi(UBYTE Char)
  2989. {
  2990.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2991.         (* ConDump)("^[",2);
  2992.  
  2993.     DoCancel();
  2994.  
  2995.     InSequence = TRUE;
  2996.  
  2997.     return(ParseCode('['));
  2998. }
  2999.  
  3000. STATIC STRPTR    CR_Translation,
  3001.         LF_Translation;
  3002. STATIC WORD    CR_Trans_Len,
  3003.         LF_Trans_Len;
  3004.  
  3005. STATIC LONG __regargs
  3006. Translate_CR_LF_1(register STRPTR Data,register LONG Size)
  3007. {
  3008.     register STRPTR    String    = Data;
  3009.     register LONG    Count    = 0;
  3010.     register UBYTE    c;
  3011.  
  3012.     while(Size--)
  3013.     {
  3014.         switch(c = *Data++)
  3015.         {
  3016.             case '\r':
  3017.  
  3018.                 if(CR_Trans_Len)
  3019.                 {
  3020.                     *String++ = *CR_Translation;
  3021.  
  3022.                     Count++;
  3023.                 }
  3024.  
  3025.                 break;
  3026.  
  3027.             case '\n':
  3028.  
  3029.                 if(LF_Trans_Len)
  3030.                 {
  3031.                     *String++ = *LF_Translation;
  3032.  
  3033.                     Count++;
  3034.                 }
  3035.  
  3036.                 break;
  3037.  
  3038.             default:
  3039.  
  3040.                 *String++ = c;
  3041.  
  3042.                 Count++;
  3043.  
  3044.                 break;
  3045.         }
  3046.     }
  3047.  
  3048.     return(Count);
  3049. }
  3050.  
  3051. STATIC LONG __regargs
  3052. Translate_CR_LF_2x2(register STRPTR Data,register LONG Size)
  3053. {
  3054.     register STRPTR    String    = Data;
  3055.     register LONG    Count    = 0;
  3056.     register UBYTE    c;
  3057.  
  3058.     /* ALWAYS */
  3059.     {
  3060.         register BOOL GotIt = FALSE;
  3061.         register LONG i;
  3062.  
  3063.         for(i = 0 ; i < Size ; i++)
  3064.         {
  3065.             if(String[i] == '\r' || String[i] == '\n')
  3066.             {
  3067.                 GotIt = TRUE;
  3068.  
  3069.                 break;
  3070.             }
  3071.         }
  3072.  
  3073.         if(GotIt)
  3074.         {
  3075.             CopyMem(Data,StripBuffer,Size);
  3076.  
  3077.             String    = Data;
  3078.             Data    = StripBuffer;
  3079.         }
  3080.         else
  3081.             return(Size);
  3082.     }
  3083.  
  3084.     while(Size--)
  3085.     {
  3086.         switch(c = *Data++)
  3087.         {
  3088.             case '\r':
  3089.  
  3090.                 if(CR_Trans_Len)
  3091.                 {
  3092.                     register WORD i;
  3093.  
  3094.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3095.                     {
  3096.                         *String++ = CR_Translation[i];
  3097.  
  3098.                         Count++;
  3099.                     }
  3100.                 }
  3101.  
  3102.                 break;
  3103.  
  3104.             case '\n':
  3105.  
  3106.                 if(LF_Trans_Len)
  3107.                 {
  3108.                     register WORD i;
  3109.  
  3110.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3111.                     {
  3112.                         *String++ = LF_Translation[i];
  3113.  
  3114.                         Count++;
  3115.                     }
  3116.                 }
  3117.  
  3118.                 break;
  3119.  
  3120.             default:
  3121.  
  3122.                 *String++ = c;
  3123.  
  3124.                 Count++;
  3125.  
  3126.                 break;
  3127.         }
  3128.     }
  3129.  
  3130.     return(Count);
  3131. }
  3132.  
  3133. STATIC LONG __regargs
  3134. Translate_CR_LF_2LF(register STRPTR Data,register LONG Size)
  3135. {
  3136.     register STRPTR    String    = Data;
  3137.     register LONG    Count    = 0;
  3138.     register UBYTE    c;
  3139.  
  3140.     /* ALWAYS */
  3141.     {
  3142.         register BOOL GotIt = FALSE;
  3143.         register LONG i;
  3144.  
  3145.         for(i = 0 ; i < Size ; i++)
  3146.         {
  3147.             if(String[i] == '\n')
  3148.             {
  3149.                 GotIt = TRUE;
  3150.  
  3151.                 break;
  3152.             }
  3153.         }
  3154.  
  3155.         if(GotIt)
  3156.         {
  3157.             CopyMem(Data,StripBuffer,Size);
  3158.  
  3159.             String    = Data;
  3160.             Data    = StripBuffer;
  3161.         }
  3162.         else
  3163.             return(Size);
  3164.     }
  3165.  
  3166.     while(Size--)
  3167.     {
  3168.         switch(c = *Data++)
  3169.         {
  3170.             case '\r':
  3171.  
  3172.                 if(CR_Trans_Len)
  3173.                 {
  3174.                     register WORD i;
  3175.  
  3176.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3177.                     {
  3178.                         *String++ = CR_Translation[i];
  3179.  
  3180.                         Count++;
  3181.                     }
  3182.                 }
  3183.  
  3184.                 break;
  3185.  
  3186.             case '\n':
  3187.  
  3188.                 if(LF_Trans_Len)
  3189.                 {
  3190.                     register WORD i;
  3191.  
  3192.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3193.                     {
  3194.                         *String++ = LF_Translation[i];
  3195.  
  3196.                         Count++;
  3197.                     }
  3198.                 }
  3199.  
  3200.                 break;
  3201.  
  3202.             default:
  3203.  
  3204.                 *String++ = c;
  3205.  
  3206.                 Count++;
  3207.  
  3208.                 break;
  3209.         }
  3210.     }
  3211.  
  3212.     return(Count);
  3213. }
  3214.  
  3215. STATIC LONG __regargs
  3216. Translate_CR_LF_2CR(register STRPTR Data,register LONG Size)
  3217. {
  3218.     register STRPTR    String    = Data;
  3219.     register LONG    Count    = 0;
  3220.     register UBYTE    c;
  3221.  
  3222.     /* ALWAYS */
  3223.     {
  3224.         register BOOL GotIt = FALSE;
  3225.         register LONG i;
  3226.  
  3227.         for(i = 0 ; i < Size ; i++)
  3228.         {
  3229.             if(String[i] == '\r')
  3230.             {
  3231.                 GotIt = TRUE;
  3232.  
  3233.                 break;
  3234.             }
  3235.         }
  3236.  
  3237.         if(GotIt)
  3238.         {
  3239.             CopyMem(Data,StripBuffer,Size);
  3240.  
  3241.             String    = Data;
  3242.             Data    = StripBuffer;
  3243.         }
  3244.         else
  3245.             return(Size);
  3246.     }
  3247.  
  3248.     while(Size--)
  3249.     {
  3250.         switch(c = *Data++)
  3251.         {
  3252.             case '\r':
  3253.  
  3254.                 if(CR_Trans_Len)
  3255.                 {
  3256.                     register WORD i;
  3257.  
  3258.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3259.                     {
  3260.                         *String++ = CR_Translation[i];
  3261.  
  3262.                         Count++;
  3263.                     }
  3264.                 }
  3265.  
  3266.                 break;
  3267.  
  3268.             case '\n':
  3269.  
  3270.                 if(LF_Trans_Len)
  3271.                 {
  3272.                     register WORD i;
  3273.  
  3274.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3275.                     {
  3276.                         *String++ = LF_Translation[i];
  3277.  
  3278.                         Count++;
  3279.                     }
  3280.                 }
  3281.  
  3282.                 break;
  3283.  
  3284.             default:
  3285.  
  3286.                 *String++ = c;
  3287.  
  3288.                 Count++;
  3289.  
  3290.                 break;
  3291.         }
  3292.     }
  3293.  
  3294.     return(Count);
  3295. }
  3296.  
  3297. VOID
  3298. Update_CR_LF_Translation()
  3299. {
  3300.     Forbid();
  3301.  
  3302.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CRLF || Config -> TerminalConfig -> ReceiveCR == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_CRLF)
  3303.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize / 2;
  3304.     else
  3305.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize;
  3306.  
  3307.     switch(Config -> TerminalConfig -> ReceiveCR)
  3308.     {
  3309.         case EOL_IGNORE:
  3310.  
  3311.             CR_Trans_Len = 0;
  3312.             break;
  3313.  
  3314.         case EOL_CR:
  3315.  
  3316.             CR_Trans_Len    = 1;
  3317.             CR_Translation    = "\r";
  3318.             break;
  3319.  
  3320.         case EOL_LF:
  3321.  
  3322.             CR_Trans_Len    = 1;
  3323.             CR_Translation    = "\n";
  3324.             break;
  3325.  
  3326.         case EOL_CRLF:
  3327.  
  3328.             CR_Trans_Len    = 2;
  3329.             CR_Translation    = "\r\n";
  3330.             break;
  3331.  
  3332.         case EOL_LFCR:
  3333.  
  3334.             CR_Trans_Len    = 2;
  3335.             CR_Translation    = "\n\r";
  3336.             break;
  3337.     }
  3338.  
  3339.     switch(Config -> TerminalConfig -> ReceiveLF)
  3340.     {
  3341.         case EOL_IGNORE:
  3342.  
  3343.             LF_Trans_Len = 0;
  3344.             break;
  3345.  
  3346.         case EOL_LF:
  3347.  
  3348.             LF_Trans_Len    = 1;
  3349.             LF_Translation    = "\n";
  3350.             break;
  3351.  
  3352.         case EOL_CR:
  3353.  
  3354.             LF_Trans_Len    = 1;
  3355.             LF_Translation    = "\r";
  3356.             break;
  3357.  
  3358.         case EOL_LFCR:
  3359.  
  3360.             LF_Trans_Len    = 2;
  3361.             LF_Translation    = "\n\r";
  3362.             break;
  3363.  
  3364.         case EOL_CRLF:
  3365.  
  3366.             LF_Trans_Len    = 2;
  3367.             LF_Translation    = "\r\n";
  3368.             break;
  3369.     }
  3370.  
  3371.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CR && Config -> TerminalConfig -> ReceiveLF == EOL_LF)
  3372.         Translate_CR_LF = NULL;
  3373.     else
  3374.     {
  3375.         if(LF_Trans_Len <= 1 && CR_Trans_Len <= 1)
  3376.             Translate_CR_LF = Translate_CR_LF_1;
  3377.         else
  3378.         {
  3379.             if(LF_Trans_Len == 2 && CR_Trans_Len == 2)
  3380.                 Translate_CR_LF = Translate_CR_LF_2x2;
  3381.             else
  3382.             {
  3383.                 if(LF_Trans_Len == 2)
  3384.                     Translate_CR_LF = Translate_CR_LF_2LF;
  3385.                 else
  3386.                 {
  3387.                     if(CR_Trans_Len == 2)
  3388.                         Translate_CR_LF = Translate_CR_LF_2CR;
  3389.                     else
  3390.                         Translate_CR_LF = Translate_CR_LF_1;
  3391.                 }
  3392.             }
  3393.         }
  3394.     }
  3395.  
  3396.     Permit();
  3397. }
  3398.